#define STRICT
#define WIN32_LEAN_AND_MEAN

#include "stdafx.h"
#include <windows.h>
#include <time.h>
#include "Scene.h"
#include "..\Render\Render.h"
#include "..\GUI\GUI.h"
#include "Viewer.h"
#include "Model.h"
#include "..\Window.h"

#include <vector>
#include "..\..\Global\globaldef.h"


Server CViewer::g_server;
CViewer::ViewerMode CViewer::Mode = CViewer::NAVIGATE_FREEVIEW;
CViewer::ViewerMode CViewer::LastMode = CViewer::NAVIGATE_FREEVIEW;

D3DXVECTOR3 g_CameraPosition = D3DXVECTOR3(0.0f,0.0f,0.0f);
float g_CameraAngles[] = {0.0f,0.0f};

float g_time = 0.0f;
Model* g_SelectedObject = NULL;


std::string CViewer::GetFilename(std::string filePath) {

	int idx = filePath.find_last_of('/')+1;
	if(idx < 0)
		return filePath;

	return filePath.substr(idx);
}

void CViewer::GetServer(Server** pServer) {

	if(pServer)
		*pServer = &CViewer::g_server;
}

void CViewer::Error(const char* format,...) {

	char Buffer[512] = {'\0'};
	char final[512] = {'\0'};

	va_list	args; 
	va_start (args,format); 
	vsprintf_s(Buffer, 512,format,args); 
	perror(Buffer); 
	va_end(args); 

}


//void CViewer::SetSelection(const Model* pMesh) {
//
//}
//
//void CViewer::GetSelection(Model** pMesh) {
//
//}


void CViewer::OnUpdate()
{
	CViewer::g_server.Update();
	GUI::Update();
	std::vector<Connection::Packet> packetList;

	for(uint c = 0; c < CViewer::g_server.ClientCount(); c++) {

		if(CViewer::g_server.GetDataPackets(&packetList,c)) {

			Model* pLastModel = NULL;
			uint lastType = 0;

			for(std::vector<Connection::Packet>::iterator i = packetList.begin(); i != packetList.end(); i++) {
			
				switch(i->header.packetID) {

					case UPDATE_MESHGEOMETRY:
					case UPDATE_TRANSFORM:
						{
							Model* pCurrentModel;
							char* pIdentity = i->pData;
							if(Scene::GetGeometry(&pCurrentModel, (tCharBuffer*)pIdentity)) {

								if(pCurrentModel == pLastModel && lastType == i->header.packetID)
									continue;

								lastType = i->header.packetID;
								pLastModel = pCurrentModel;
							}
						}break;
				}
				
				CViewer::PacketHandler(&(*i));
			}
		}
	}

}

void CViewer::OnInitalize()
{
	CViewer::g_server.Initalize();
	CViewer::g_server.BeginListenForClients();

	Render::Singleton()->Create(CWindow::GetHandle());
	Render::Singleton()->ShowGrid(true);

	Render::Singleton()->SetCameraFrameNavigation(D3DXVECTOR3(-2.4342170, 10.1646695, -2.2819395), -11.69f,0.81f);
	
	GUI::Create();
	Scene::Create();
			
	CWindow::CenterMouse();

	/*Model* pTest = NULL;
	Scene::ReadFromDisk("pPlaneShape1", &pTest);
	Scene::InsertGeometry(pTest);

	Model* pInstTest = NULL;
	Scene::ReadFromDisk("pConeShape1", &pInstTest);
	pTest->AddChildInstancing(pInstTest, NULL,NULL);*/
}

void CViewer::OnShutdown()
{	
	Scene::Release();
	Render::Singleton()->Release();
	CViewer::g_server.EndListenForClients();
	CViewer::g_server.Release();

}

void CViewer::OnKeyboardEvent(UINT *pKeyboardState) {

	
	if(pKeyboardState[(UINT)'W'] & KEY_DOWN || pKeyboardState[(UINT)'w'] & KEY_DOWN)
		Render::Singleton()->SetCameraFrameNavigation(D3DXVECTOR3(0,0,.3),0,0);
	
	if(pKeyboardState[(UINT)'S'] & KEY_DOWN || pKeyboardState[(UINT)'s'] & KEY_DOWN)
		Render::Singleton()->SetCameraFrameNavigation(D3DXVECTOR3(0,0,-.3),0,0);
		
	if(pKeyboardState[(UINT)'A'] & KEY_DOWN || pKeyboardState[(UINT)'a'] & KEY_DOWN)
		Render::Singleton()->SetCameraFrameNavigation(D3DXVECTOR3(0.3,0,0),0,0);
			
	if(pKeyboardState[(UINT)'D'] & KEY_DOWN || pKeyboardState[(UINT)'d'] & KEY_DOWN)
		Render::Singleton()->SetCameraFrameNavigation(D3DXVECTOR3(-0.3,0,0),0,0);

	if(pKeyboardState[(UINT)'R'] & KEY_DOWN || pKeyboardState[(UINT)'r'] & KEY_DOWN) {
		Render::Singleton()->ReloadResources();

		/*g_GUI.Release();
		g_GUI.Create();
		g_pClientPanel = g_GUI.CreatePanel();
		g_pObjectPanel = g_GUI.CreatePanel();*/
	}

}

void CViewer::OnMouseEvent(const int dxMouse, const int dyMouse, const int leftButton, const int rightButton) {

	if(rightButton == 1) {

		switch(CViewer::Mode) {

			case CViewer::NAVIGATE_UI:
				CViewer::Mode = CViewer::LastMode;
				GUI::EnableCursor(false);
				break;
			case CViewer::NAVIGATE_FREEVIEW: 
			case CViewer::NAVIGATE_MAYA:
				CViewer::LastMode = CViewer::Mode;
				CViewer::Mode = CViewer::NAVIGATE_UI;
				GUI::EnableCursor(true);
				break;
		}
	}

	switch(CViewer::Mode) {
		
		case CViewer::NAVIGATE_FREEVIEW: {
		
			CWindow::CenterMouse();
			Render::Singleton()->SetCameraFrameNavigation(g_CameraPosition, g_CameraAngles[0],g_CameraAngles[1]);
			g_CameraAngles[0] = (float)(dxMouse) * 0.001f;
			g_CameraAngles[1] = (float)(dyMouse) * 0.001f;
		}
		break;

		case CViewer::NAVIGATE_UI: {

			CWindow::CenterMouse();
			GUI::OnMouseEvent(dxMouse, dyMouse, 
				leftButton == 1 ? GUI::BUTTON_DOWN : GUI::BUTTON_UP, 
				rightButton == 1 ? GUI::BUTTON_DOWN : GUI::BUTTON_UP);
	   }
	   break;
	}
}
void CViewer::OnRenderFrame( void )
{

	/*
	if(CViewer::g_server.ClientCount() == 0 && Model::g_streamMeshes.size() > 0) {
		for(UINT i = 0; i < Model::g_streamMeshes.size(); i++)
			Model::g_streamMeshes[i].Release();
		Model::g_streamMeshes.clear();
	}*/
//return;
	Render::Singleton()->BeginRendering();
	g_time += 0.05f;

	Scene::Draw();
	GUI::Draw();
	Render::Singleton()->EndRendering();
}
